package myTest;

import index.Indexator_WithPreliminarySorting;
import index.Indexator_WithTempFiles;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import net.barashev.seclub.CmdLineOptions;
import net.barashev.seclub.io.BufferManager;
import net.barashev.seclub.io.DataMarshaller;
import net.barashev.seclub.io.IteratingSlot;
import net.barashev.seclub.io.Sorter;
import net.barashev.seclub.io.file.DiskFileManager;
import net.barashev.seclub.io.file.FileManager;
import net.barashev.seclub.io.file.VFile;
import net.barashev.seclub.io.marshaller.IntegerComparator;
import net.barashev.seclub.io.marshaller.IntegerMarshaller;

import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;

public class DummySearcher {
	private BufferManager bufferMgr;
	private FileManager fileMgr;
	
	
	public DummySearcher(BufferManager bufferMgr, DiskFileManager fileMgr) {
		this.bufferMgr = bufferMgr;
		this.fileMgr = fileMgr;
	}

	public static void main(String[] args) throws IOException, CmdLineException {
		System.out.println("START DummySearcher \n");
		CmdLineOptions options = new CmdLineOptions();
		CmdLineParser parser = new CmdLineParser(options);
		parser.parseArgument(args);  		

		
		DiskFileManager fileMgr = new DiskFileManager(options.index_dir);
		BufferManager bufferMgr = new BufferManager(options.block_size_bytes,
				options.buffer_size_blocks);
		
		DummySearcher dummySearcher = new DummySearcher(bufferMgr,fileMgr);
		
		BufferedReader inputReader = new BufferedReader(new InputStreamReader(
				System.in));
		String input;
		System.out
				.println("Type your query separating keywords with spaces, like this:\n\nfoo bar\n\n Enter empty string to exit.");
		do {
			input = inputReader.readLine();
			if(fileMgr.getFile(input)==null){
				fileMgr.createFile(input, new IntegerMarshaller());
			}
			List<Integer> result = dummySearcher.search(input);
			if (result != null) {
				System.out.println("Matching docids: " + result);
			} else {
				System.out.println("No matches");
			}
		} while (!"".equals(input));
	}
	
	public List<Integer> search(String query) throws IOException {
		List<VFile<Integer>> pls = new ArrayList<VFile<Integer>>();
		for (StringTokenizer tkzr = new StringTokenizer(query); tkzr
				.hasMoreElements();) {
			VFile<Integer> pl = this.fileMgr.getFile(tkzr.nextToken());
			if (pl == null) {
				return null;
			} else {
				pls.add(pl);
			}
		}
		if (pls.isEmpty()) {
			return null;
		}
		List<Integer> result = new ArrayList<Integer>();
		HashMap<IteratingSlot<Integer, DataMarshaller<Integer>>, Integer> heads = Sorter
				.initialPullHeads(this.bufferMgr, pls);
		if (intersectPostingLists(heads, result)) {
			return result;
		}
		return null;
	}
	
	private boolean intersectPostingLists(
			HashMap<IteratingSlot<Integer, DataMarshaller<Integer>>, Integer> heads,
			List<Integer> result) throws IOException {
		int size = heads.size();
		while (size == heads.size()) {
			Integer sameDocid = getSameValueFromTops(heads);
			if (sameDocid != null) {
				result.add(sameDocid);
				pullAll(heads);
			} else {
				Sorter.findMinAndPull(new IntegerComparator(), heads);
			}
		}
		return true;
	}
	private void pullAll(
			HashMap<IteratingSlot<Integer, DataMarshaller<Integer>>, Integer> heads)
			throws IOException {
		for (Iterator<Map.Entry<IteratingSlot<Integer, DataMarshaller<Integer>>, Integer>> it = heads
				.entrySet().iterator(); it.hasNext();) {
			Map.Entry<IteratingSlot<Integer, DataMarshaller<Integer>>, Integer> entry = it
					.next();
			IteratingSlot<Integer, DataMarshaller<Integer>> slot = entry
					.getKey();
			Integer idxRecord = entry.getValue();
			if (idxRecord == slot.getRecordCount()) {
				if (slot.pull()) {
					idxRecord = 0;
					entry.setValue(0);
				} else {
					it.remove();
					continue;
				}
			} else {
				entry.setValue(idxRecord + 1);
			}
		}
	}

	private Integer getSameValueFromTops(
			HashMap<IteratingSlot<Integer, DataMarshaller<Integer>>, Integer> heads)
			throws IOException {
		Integer resultDocid = null;
		for (Iterator<Map.Entry<IteratingSlot<Integer, DataMarshaller<Integer>>, Integer>> it = heads
				.entrySet().iterator(); it.hasNext();) {
			Map.Entry<IteratingSlot<Integer, DataMarshaller<Integer>>, Integer> entry = it
					.next();
			IteratingSlot<Integer, DataMarshaller<Integer>> slot = entry
					.getKey();
			Integer idxRecord = entry.getValue();
			if (idxRecord == slot.getRecordCount()) {
				if (slot.pull()) {
					idxRecord = 0;
					entry.setValue(0);
				} else {
					it.remove();
					resultDocid = null;
					break;
				}
			}
			Integer curDocid = slot.getBlock(0).get(idxRecord);
			if ((resultDocid != null) && !resultDocid.equals(curDocid)) {
				return null;
			}
			resultDocid = curDocid;
		}
		return resultDocid;

	}
}
